package actors

import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.{Behaviors, TimerScheduler}
import dao._
import models.Tables.MissionRow
import org.joda.time.DateTime
import tool.{Pojo, Tool}
import tool.Pojo._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.duration.FiniteDuration
import scala.language.postfixOps


/**
 * Created by yz on 13/4/2020
 */
object MissionManager {

  sealed trait Message

  case class MissionWrap(mission: MissionRow) extends Message

  case object Ask extends Message

  case object TimerKey

  def apply()(implicit missionDao: MissionDao): Behavior[Message] = Behaviors.setup { context =>

    val availCpu = Tool.availCpu
    missionDao.selectAll("running").map { missions =>
      missions.foreach { mission =>
        val missionWrap = MissionWrap(mission)
        context.self ! missionWrap
      }
    }
    val missionExecutor = context.spawn(MissionExecutor(), "missionEntrance")
    Behaviors.withTimers { timers =>
      timers.startTimerAtFixedRate(TimerKey, Ask, 3 seconds)
      Behaviors.receiveMessage[Message] { message =>
        message match {
          case Ask =>
            missionDao.selectAll("running").map { missions =>
              val totalUseCpu = missions.map(x => x.cpu).sum
              val remainCpu = availCpu - totalUseCpu
              missionDao.selectAll("wait").map { totalMissions =>
                val canRunMissions = totalMissions.filter(x => x.cpu <= remainCpu).sortBy(_.startTime.getMillis)
                if (!canRunMissions.isEmpty) {
                  val mission = canRunMissions(0)
                  missionExecutor ! MissionExecutor.MissionStart(mission)
                }
              }
            }
            Behaviors.same
          case MissionWrap(mission) =>
            val newMission = mission.copy(state = "wait")
            missionDao.update(newMission)
            Behaviors.same
        }

      }

    }

  }

}
